package cn.lichenfei.ffmpeg.common;

import ws.schild.jave.Encoder;
import ws.schild.jave.EncoderException;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;
import ws.schild.jave.progress.EncoderProgressListener;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.function.Consumer;

/**
 * 音视频工具类：
 * <br/>
 * 参考文档：
 */
public class FFmpegUtils {


    /**
     * 视频转为mp4
     *
     * @param input
     * @param output
     * @throws EncoderException
     * @throws MalformedURLException
     */
    public static void videoToMp4(String input, String output, EncoderProgressListener encoderProgressListener) throws EncoderException, MalformedURLException {
        VideoAttributes videoAttributes = new VideoAttributes();
        videoAttributes.setCodec("libx264");
        AudioAttributes audioAttributes = new AudioAttributes();
        audioAttributes.setCodec("aac");
        //
        EncodingAttributes encodingAttributes = new EncodingAttributes();
        encodingAttributes.setOutputFormat("mp4");
        encodingAttributes.setVideoAttributes(videoAttributes);
        encodingAttributes.setAudioAttributes(audioAttributes);
        // 编码
        encode(input, new File(output), encodingAttributes, encoderProgressListener);
    }

    /**
     * 音频转为mp3
     *
     * @param input
     * @param output
     * @throws EncoderException
     * @throws MalformedURLException
     */
    public static void audioToMp3(String input, String output, EncoderProgressListener encoderProgressListener) throws EncoderException, MalformedURLException {
        AudioAttributes audioAttributes = new AudioAttributes();
        audioAttributes.setCodec("libmp3lame");
        //
        EncodingAttributes encodingAttributes = new EncodingAttributes();
        encodingAttributes.setOutputFormat("mp3");
        encodingAttributes.setAudioAttributes(audioAttributes);
        // 编码
        encode(input, new File(output), encodingAttributes, encoderProgressListener);
    }

    /**
     * 剪切音视频:返回 star:[offset] -> end:[duration+offset]
     *
     * @param offset                  开始时间:秒
     * @param duration                持续时间:秒
     * @param input
     * @param output
     * @param encoderProgressListener
     * @throws EncoderException
     * @throws MalformedURLException
     */
    public static void cut(Float offset, Float duration, String input, String output, EncoderProgressListener encoderProgressListener) throws EncoderException, MalformedURLException {
        //
        EncodingAttributes encodingAttributes = new EncodingAttributes();
        encodingAttributes.setAudioAttributes(new AudioAttributes().setCodec(AudioAttributes.DIRECT_STREAM_COPY));
        encodingAttributes.setVideoAttributes(new VideoAttributes().setCodec(VideoAttributes.DIRECT_STREAM_COPY));
        encodingAttributes.setDuration(duration);
        encodingAttributes.setOffset(offset);
        // 编码
        encode(input, new File(output), encodingAttributes, encoderProgressListener);
    }

    /**
     * 执行编码命命令
     *
     * @param input
     * @param output
     * @param encodingAttributes
     * @throws EncoderException
     * @throws MalformedURLException
     */
    private static void encode(String input, File output, EncodingAttributes encodingAttributes, EncoderProgressListener encoderProgressListener) throws EncoderException, MalformedURLException {
        Encoder encoder = new Encoder();
        MultimediaObject multimediaObject;
        if (input.startsWith("http")) {
            multimediaObject = new MultimediaObject(new URL(input));
        } else {
            multimediaObject = new MultimediaObject(new File(input));
        }
        encoder.encode(multimediaObject, output, encodingAttributes, encoderProgressListener);
    }

    /**
     * 使用命令的方式调用ffmpeg功能
     *
     * @param args
     */
    private static void command(String... args) {
        try (ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor()) {
            System.err.println("++++++++++++++++++++++++++++++++++++++++ <Start> ++++++++++++++++++++++++++++++++++++++++");
            for (String arg : args) {
                ffmpeg.addArgument(arg);
            }
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                String lineStr;
                while ((lineStr = br.readLine()) != null) {
                    System.out.println(lineStr);
                }
            }
            System.err.println("++++++++++++++++++++++++++++++++++++++++ <End> ++++++++++++++++++++++++++++++++++++++++");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取媒体数据
     *
     * @param input
     * @return
     * @throws EncoderException
     */
    public static MultimediaInfo getMultimediaInfo(String input) throws EncoderException {
        MultimediaObject multimediaObject = new MultimediaObject(new File(input));
        return multimediaObject.getInfo();
    }

    /**
     * 获取视频封面
     * <p>
     * ffmpeg -y -i input.mp4 -ss 5 -vframes 1 output.jpg
     * `-y` 自动覆盖输出文件
     * `-i` 表示输入文件的路径
     * `-ss` 后面跟着的是要截取的时间点
     * `-vframes 1` 表示只截取一帧
     * `output.jpg` 表示输出文件
     *
     * @param input
     * @param seconds
     * @param consumer : 任务完成后执行
     * @return
     */
    public static String getVideoCover(File input, long seconds) {
        String output = input.getParent() + "/" + input.getName() + ".jpg"; // 生产的视频封面地址
        command("-y", "-i", input.getPath(), "-ss", seconds + "", "-vframes", "1", output);
        return output;
    }

    /**
     * 视频切片
     * <p>
     * ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename output_%03d.ts output.m3u8
     * <p>
     * 分辨率：-vf scale=1920:1080 ; -vf scale=1280:720
     *
     * @param input  : 输入视频
     * @param output : 输出目录 TODO: output应该是一个目录
     * @return
     */
    public static File m3u8(String input, String output) {
        File file = new File(output);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
        }
        String m3u8 = file.getPath() + "/video.m3u8";
        String ts = file.getPath() + "/video_%03d.ts";
        command("-i",
                input,
                "-c:v",
                "copy",
                //"libx264",
                "-c:a",
                "copy",
                "-f",
                "hls",
                "-hls_time",
                "10",
                "-hls_list_size",
                "0",
                "-hls_segment_filename",
                ts,
                m3u8
        );
        return new File(m3u8);
    }

    /**
     * 测试执行命令
     *
     * @param args
     */
    public static void main(String[] args) throws EncoderException, MalformedURLException {
        /*

        String input = "C:\\Users\\Administrator\\Documents\\WeChat Files\\wxid_bij0qf56w0ib21\\FileStorage\\File\\2023-08\\0c10982d96771ec38f3e6b3cbf5fe89a_raw-0001.MPG";
        String output = "F:/ToMp4ToMp4.mp4";
        command("-i", input, "-c:v", "libx264", output, "-y");

        */

        //String input = "F:\\迅雷下载\\阳光电影dy.ygdy8.com.疾速追杀4.2023.HD.1080P.中英双字.mkv";
        //String output = "F:\\迅雷下载\\阳光电影dy.ygdy8.com.疾速追杀4.2023.HD.1080P.中英双字___.mkv";

        /*cut(55.0F, 80F, input, output, new EncoderProgressListener() {
            @Override
            public void sourceInfo(MultimediaInfo info) {

            }

            @Override
            public void progress(int permil) {
                System.out.println(permil);
            }

            @Override
            public void message(String message) {

            }
        });*/

        //MultimediaInfo multimediaInfo = getMultimediaInfo("C:\\Users\\ljd\\Desktop\\8f1e9de52d0be8d4167859ffbbc5ab86.mp4");

        //getVideoCover(new File("C:/Users/ljd/Desktop/eee40819300dcaf58b2a70e4360fb25b.mp4"), 3, new Consumer<String>() {
        //    @Override
        //    public void accept(String s) {
        //        System.out.println(s);
        //    }
        ///});

        //Encoder encoder = new Encoder();
        //System.out.println(Arrays.toString(encoder.getSupportedEncodingFormats()));


        // m3u8("D:\\迅雷下载\\15114f31b3d64daa8f4ade20dd256cca.mp4", "D:/my_static");

        // 降低视频分辨率
        // ffmpeg -i input.mp4 -vf scale=1920:1080 output.mp4
        //command("-i", "D:/迅雷下载/15114f31b3d64daa8f4ade20dd256cca.mp4", "-vf", "scale=1920:1080","D:/迅雷下载/15114f31b3d64daa8f4ade20dd256cca_.mp4");

        // 降低视频质量
        //ffmpeg -i input.mp4 -crf 28 output.mp4
        command("-y", "-i", "D:/迅雷下载/15114f31b3d64daa8f4ade20dd256cca.mp4", "-s", "1280x720", "-crf", "28", "D:/迅雷下载/15114f31b3d64daa8f4ade20dd256cca_.mp4");
    }


}
